const interfaceMethodModel = require('../models/interfaceMethod.js');
const _ = require('underscore');
const url = require('url');
const baseController = require('./base.js');
const yapi = require('../yapi.js');
const mergeJsonSchema = require('../../common/mergeJsonSchema');

function handleHeaders(values){
    let isfile = false,
        isHavaContentType = false;
    if (values.req_body_type === 'form') {
        values.req_body_form.forEach(item => {
            if (item.type === 'file') {
                isfile = true;
            }
        });

        values.req_headers.map(item => {
            if (item.name === 'Content-Type') {
                item.value = isfile ? 'multipart/form-data' : 'application/x-www-form-urlencoded';
                isHavaContentType = true;
            }
        });
        if (isHavaContentType === false) {
            values.req_headers.unshift({
                name: 'Content-Type',
                value: isfile ? 'multipart/form-data' : 'application/x-www-form-urlencoded'
            });
        }
    } else if (values.req_body_type === 'json') {
        values.req_headers
            ? values.req_headers.map(item => {
                if (item.name === 'Content-Type') {
                    item.value = 'application/json';
                    isHavaContentType = true;
                }
            })
            : [];
        if (isHavaContentType === false) {
            values.req_headers = values.req_headers || [];
            values.req_headers.unshift({
                name: 'Content-Type',
                value: 'application/json'
            });
        }
    }
}


class interfaceMethodController extends baseController {
    constructor(ctx) {
        super(ctx);
        this.Model = yapi.getInst(interfaceMethodModel);
    }
                /**添加接口方法**/
    async add(ctx) {
        let params = ctx.params;

        if (!this.$tokenAuth) {
            let auth = await this.checkAuth(params.uid, 'project', 'edit');

            if (!auth) {
                return (ctx.body = yapi.commons.resReturn(null, 40033, '没有权限'));
            }
        }
        params.method = params.method || 'GET';
        params.res_body_is_json_schema = _.isUndefined(params.res_body_is_json_schema)
            ? false
            : params.res_body_is_json_schema;
        params.req_body_is_json_schema = _.isUndefined(params.req_body_is_json_schema)
            ? false
            : params.req_body_is_json_schema;
        params.method = params.method.toUpperCase();
        params.req_params = params.req_params || [];
        params.res_body_type = params.res_body_type ? params.res_body_type.toLowerCase() : 'json';
        // let http_path = url.parse(params.path, true);
        //
        // if (!yapi.commons.verifyPath(http_path.pathname)) {
        //     return (ctx.body = yapi.commons.resReturn(
        //         null,
        //         400,
        //         'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成'
        //     ));
        // }

        handleHeaders(params);

        // params.query_path = {};
        // params.query_path.path = http_path.pathname;
        // params.query_path.params = [];
        // Object.keys(http_path.query).forEach(item => {
        //     params.query_path.params.push({
        //         name: item,
        //         value: http_path.query[item]
        //     });
        // });

        let checkRepeat = await this.Model.checkRepeat(params.infid, params.mname);

        if (checkRepeat > 0) {
            return (ctx.body = yapi.commons.resReturn(
                null,
                40022,
                '已存在的接口:' + params.path
            ));
        }

        let data = Object.assign(params, {
            uid: this.getUid(),
            ctime: yapi.commons.time(),
            etime: yapi.commons.time()
        });

        // 新建接口的人成为项目dev  如果不存在的话
        // 命令行导入时无法获知导入接口人的信息，其uid 为 999999
        let uid = this.getUid();

        if (this.getRole() !== 'admin' && uid !== 999999) {
            let userdata = await yapi.commons.getUserdata(uid, 'dev');
            // 检查一下是否有这个人
            let check = await this.projectModel.checkMemberRepeat(params.uid, uid);
            if (check === 0 && userdata) {
                await this.projectModel.addMember(params.uid, [userdata]);
            }
        }

        let result = await this.Model.save(data);
        //动态日志
        // yapi.emitHook('interface_add', result).then();
        // this.catModel.get(params.catid).then(cate => {
        //     let username = this.getUsername();
        //     let title = `<a href="/user/profile/${this.getUid()}">${username}</a> 为分类 <a href="/project/${
        //         params.project_id
        //     }/interface/api/cat_${params.catid}">${cate.name}</a> 添加了接口 <a href="/project/${
        //         params.project_id
        //     }/interface/api/${result._id}">${data.title}</a> `;
        //
        //     yapi.commons.saveLog({
        //         content: title,
        //         type: 'project',
        //         uid: this.getUid(),
        //         username: username,
        //         typeid: params.project_id
        //     });
        //     this.projectModel.up(params.project_id, { up_time: new Date().getTime() }).then();
        // });

        ctx.body = yapi.commons.resReturn(result);
    }
    /**保存接口方法数据**/
    async save(ctx) {
        let params = ctx.params;

        if (!this.$tokenAuth) {
            let auth = await this.checkAuth(params.uid, 'project', 'edit');
            if (!auth) {
                return (ctx.body = yapi.commons.resReturn(null, 40033, '没有权限'));
            }
        }
        params.method = params.method || 'GET';
        params.method = params.method.toUpperCase();

        let http_path = url.parse(params.path, true);

        if (!yapi.commons.verifyPath(http_path.pathname)) {
            return (ctx.body = yapi.commons.resReturn(
                null,
                400,
                'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成'
            ));
        }

        let result = await this.Model.getByInf(params.infid, params.method, '_id res_body');

        if (result.length > 0) {
            result.forEach(async item => {
                // console.log(this.schemaMap['up'])
                let validParams = Object.assign({}, params);
                let validResult = yapi.commons.validateParams(this.schemaMap['up'], validParams);
                if (validResult.valid) {
                    let data = {};
                    data.params = validParams;

                    if(params.res_body_is_json_schema && params.dataSync === 'good'){
                        try{
                            let new_res_body = yapi.commons.json_parse(params.res_body);
                            let old_res_body = yapi.commons.json_parse(item.res_body);
                            data.params.res_body = JSON.stringify(mergeJsonSchema(old_res_body, new_res_body),null,2);
                        }catch(err){}
                    }
                    await this.up(data);
                } else {
                    return (ctx.body = yapi.commons.resReturn(null, 400, validResult.message));
                }
            });
        } else {
            let validResult = yapi.commons.validateParams(this.schemaMap['add'], params);
            if (validResult.valid) {
                let data = {};
                data.params = params;
                await this.add(data);
            } else {
                return (ctx.body = yapi.commons.resReturn(null, 400, validResult.message));
            }
        }
        ctx.body = yapi.commons.resReturn(result);
        // return ctx.body = yapi.commons.resReturn(null, 400, 'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成');
    }

    /**
     * 获取项目分组
     * @interface /interface_method/get
     * @method GET
     * @category interface
     * @foldnumber 10
     * @param {Number}   uid 接口id，不能为空
     * @returns {Object}
     * @example ./api/interface/get.json
     */
    async get(ctx) {
        let params = ctx.params;
        if (!params._id) {
            return (ctx.body = yapi.commons.resReturn(null, 400, '接口方法id不能为空'));
        }

        try {
            let result = await this.Model.get(params._id);
            ctx.body = yapi.commons.resReturn({
                curMethod: result
            });
        } catch (err) {
            ctx.body = yapi.commons.resReturn(null, 402, err.message);
        }
    }

    /**
     * 接口列表
     * @interface /interface/list
     * @method GET
     * @category interface
     * @foldnumber 10
     * @param {Number}   project_id 项目id，不能为空
     * @param {Number}   page 当前页
     * @param {Number}   limit 每一页限制条数
     * @returns {Object}
     * @example ./api/interface/list.json
     */
    async list(ctx) {
        let uid = ctx.params.uid;
        let page = ctx.request.query.page || 1,
            limit = ctx.request.query.limit || 10;
        let project = await this.projectModel.getBaseInfo(uid);
        if (!project) {
            return (ctx.body = yapi.commons.resReturn(null, 407, '不存在的项目'));
        }
        if (project.project_type === 'private') {
            if ((await this.checkAuth(project._id, 'project', 'view')) !== true) {
                return (ctx.body = yapi.commons.resReturn(null, 406, '没有权限'));
            }
        }
        if (!uid) {
            return (ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空'));
        }

        try {
            let result;
            if (limit === 'all') {
                result = await this.Model.list(uid);
            } else {
                result = await this.Model.listWithPage(uid, page, limit);
            }

            let count = await this.Model.listCount({ uid});

            ctx.body = yapi.commons.resReturn({
                count: count,
                total: Math.ceil(count / limit),
                list: result
            });
            yapi.emitHook('interface_list', result).then();
        } catch (err) {
            ctx.body = yapi.commons.resReturn(null, 402, err.message);
        }
    }

    async downloadCrx(ctx) {
        let filename = 'crossRequest.zip';
        let dataBuffer = yapi.fs.readFileSync(
            yapi.path.join(yapi.WEBROOT, 'static/attachment/cross-request.zip')
        );
        ctx.set('Content-disposition', 'attachment; filename=' + filename);
        ctx.set('Content-Type', 'application/zip');
        ctx.body = dataBuffer;
    }

    /**
     * 编辑接口
     * @interface /interface/up
     * @method POST
     * @category interface
     * @foldnumber 10
     * @param {Number}   uid 接口id，不能为空
     * @param {String}   [path] 接口请求路径
     * @param {String}   [method] 请求方式
     * @param {Array}  [req_headers] 请求的header信息
     * @param {String}  [req_headers[].name] 请求的header信息名
     * @param {String}  [req_headers[].value] 请求的header信息值
     * @param {Boolean}  [req_headers[].required] 是否是必须，默认为否
     * @param {String}  [req_headers[].desc] header描述
     * @param {String}  [req_body_type] 请求参数方式，有["form", "json", "text", "xml"]四种
     * @param {Mixed}  [req_body_form] 请求参数,如果请求方式是form，参数是Array数组，其他格式请求参数是字符串
     * @param {String} [req_body_form[].name] 请求参数名
     * @param {String} [req_body_form[].value] 请求参数值，可填写生成规则（mock）。如@email，随机生成一条email
     * @param {String} [req_body_form[].type] 请求参数类型，有["text", "file"]两种
     * @param {String} [req_body_other]  非form类型的请求参数可保存到此字段
     * @param {String}  [res_body_type] 相应信息的数据格式，有["json", "text", "xml"]三种
     * @param {String} [res_body] 响应信息，可填写任意字符串，如果res_body_type是json,则会调用mock功能
     * @param  {String} [desc] 接口描述
     * @returns {Object}
     * @example ./api/interface/up.json
     */

    async up(ctx) {
        let params = ctx.params;
        let _id = params._id;

        handleHeaders(params);
        let interfaceMethodData = await this.Model.get(_id);
        if(!interfaceMethodData){
            return (ctx.body = yapi.commons.resReturn(null, 400, '不存在的接口'));
        }
        if (!this.$tokenAuth) {
            let auth = await this.checkAuth(interfaceMethodData.uid, 'project', 'edit');
            if (!auth) {
                return (ctx.body = yapi.commons.resReturn(null, 400, '没有权限'));
            }
        }
        let data = Object.assign(
            {
                up_time: yapi.commons.time()
            },
            params
        );
        let checkRepeat = await this.Model.checkRepeat(
            interfaceMethodData._id,
            interfaceMethodData.mname
        );
        if (checkRepeat > 0) {
            return (ctx.body = yapi.commons.resReturn(
                null,
                401,
                '已存在的接口方法'
            ));
        }

        await this.Model.up(_id,data);
        ctx.body = yapi.commons.resReturn({
            upMethod: params
        });
    }
    /**
     * 删除接口
     * @interface /interface/del
     * @method GET
     * @category interface
     * @foldnumber 10
     * @param {Number}   uid 接口id，不能为空
     * @returns {Object}
     * @example ./api/interface/del.json
     */
    async del(ctx) {
        try {
            let uid = ctx.request.body.uid;

            if (!uid) {
                return (ctx.body = yapi.commons.resReturn(null, 400, '接口id不能为空'));
            }

            let data = await this.Model.get(uid);

            if (data.uid != this.getUid()) {
                let auth = await this.checkAuth(data.uid, 'project', 'danger');
                if (!auth) {
                    return (ctx.body = yapi.commons.resReturn(null, 400, '没有权限'));
                }
            }

            // let inter = await this.Model.get(id);
            let result = await this.Model.del(uid);
            yapi.emitHook('interface_del', uid).then();
            await this.caseModel.delByInterfaceId(uid);

            this.projectModel.up(data.uid, { etime: new Date().getTime() }).then();
            ctx.body = yapi.commons.resReturn(result);
        } catch (err) {
            ctx.body = yapi.commons.resReturn(null, 402, err.message);
        }
    }
}
module.exports = interfaceMethodController;
